import sensor, display, gt911
from pyb import Timer, Pin

# ---------- 触摸屏 ----------
gt911.init(bus=4, axis=0)
lcd = display.SPIDisplay(width=320, height=240, lcdtype=1)

# ---------- 文件读写 ----------
FILE_PATH = '/xunlian.txt'
COLOR_NAMES = ['red', 'green', 'blue']

# 读取阈值和 PWM 数据
def load_data():
    """返回值: thresholds(list), pwm(int)"""
    with open(FILE_PATH, 'r') as f:
        lines = [l.strip() for l in f if l.strip()]
    th_lines = lines[:-1]
    pwm_line = lines[-1]
    thresholds = [tuple(map(int, l.split())) for l in th_lines]
    pwm = int(pwm_line)
    return thresholds, pwm

# 保存阈值和 PWM 数据
def save_data(thresholds, pwm):
    """把阈值和 PWM 写回文件，保持原格式"""
    with open(FILE_PATH, 'w') as f:
        for t in thresholds:
            f.write(' '.join(map(str, t)) + '\n')
        f.write(str(pwm) + '\n')

# 读取初始数据
thresholds, light = load_data()

# ---------- PWM 初始化 ----------
tim2 = Timer(2, freq=10000)
ch = tim2.channel(1, Timer.PWM, pin=Pin("P6"))
ch.pulse_width_percent(light)

# ---------- 摄像头初始化 ----------
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000)
sensor.set_auto_gain(False)
sensor.set_auto_whitebal(False)
sensor.set_auto_exposure(False)

# ---------- 工具函数 ----------
def clamp(v, a, b):
    """限制数值范围"""
    return max(a, min(b, v))

def draw_btn(img, rect, label, color=(255, 255, 255)):
    """绘制按钮"""
    img.draw_rectangle(rect, color=color, thickness=2)
    img.draw_string(rect[0]+3, rect[1]+3, label, scale=1, color=color)

# ---------- 按钮定义 ----------
BTN_W, BTN_H = 40, 30
GAP = 3
BTN_DET_RED   = (GAP, 0, BTN_W, BTN_H)
BTN_DET_GREEN = (GAP*2+BTN_W, 0, BTN_W, BTN_H)
BTN_DET_BLUE  = (GAP*3+BTN_W*2, 0, BTN_W, BTN_H)
BTN_SET_RED   = (GAP*4+BTN_W*3, 0, BTN_W, BTN_H)
BTN_SET_GREEN = (GAP*5+BTN_W*4, 0, BTN_W, BTN_H)
BTN_SET_BLUE  = (GAP*6+BTN_W*5, 0, BTN_W, BTN_H)
BTN_EXIT      = (320 - BTN_W - GAP, 0, BTN_W, BTN_H)

PWM_BTN_W, PWM_BTN_H = 80, 30
BTN_PWM = ((320 - PWM_BTN_W)//2, 240 - PWM_BTN_H - 2, PWM_BTN_W, PWM_BTN_H)

# ---------- 滑条定义 ----------
SLIDER_W, SLIDER_H = 292, 14  # 滑条宽度和高度
SLIDER_Y0 = 40
STEP = 20
LABELS = ['Lmin','Lmax','Amin','Amax','Bmin','Bmax']
RANGE = [(0,100),(0,100),(-128,127),(-128,127),(-128,127),(-128,127)]

# 滑条透明度（0-255），默认 70% 不透明度（即 30% 透明度）
SLIDER_ALPHA = 120  # 修改这个值可以调整透明度

# ---------- 状态变量 ----------
detecting = False
detect_color = None
edit_color = None
color_map = {'red':(255,0,0),'green':(0,255,0),'blue':(0,0,255)}
pwm_editing = False
touch_released = True   # 防连击

# ---------- 主循环 ----------
while True:
    img = sensor.snapshot()
    n, pts = gt911.read_points()

    # 手指全部抬起后允许下一次点击
    if n == 0:
        touch_released = True
        pts = []

    if touch_released and n > 0:
        x, y, *_ = pts[0]

        # PWM 按钮逻辑
        bx, by, bw, bh = BTN_PWM
        if bx <= x <= bx + bw and by <= y <= by + bh:
            if not pwm_editing and not edit_color:
                pwm_editing = True
            elif pwm_editing:
                pwm_editing = False
            touch_released = False

        # EXIT 按钮逻辑
        if detecting:
            ex, ey, ew, eh = BTN_EXIT
            if ex <= x <= ex + ew and ey <= y <= ey + eh:
                detecting = False
                detect_color = None
                touch_released = False

        # 颜色按钮逻辑
        if not pwm_editing and not edit_color:
            if BTN_DET_RED[0]   < x < BTN_DET_RED[0]+BTN_DET_RED[2]   and BTN_DET_RED[1]   < y < BTN_DET_RED[1]+BTN_DET_RED[3]:
                detecting, detect_color, edit_color = True, 'red', None
                touch_released = False
            elif BTN_DET_GREEN[0] < x < BTN_DET_GREEN[0]+BTN_DET_GREEN[2] and BTN_DET_GREEN[1] < y < BTN_DET_GREEN[1]+BTN_DET_GREEN[3]:
                detecting, detect_color, edit_color = True, 'green', None
                touch_released = False
            elif BTN_DET_BLUE[0]  < x < BTN_DET_BLUE[0]+BTN_DET_BLUE[2]  and BTN_DET_BLUE[1]  < y < BTN_DET_BLUE[1]+BTN_DET_BLUE[3]:
                detecting, detect_color, edit_color = True, 'blue', None
                touch_released = False
            elif BTN_SET_RED[0]   < x < BTN_SET_RED[0]+BTN_SET_RED[2]   and BTN_SET_RED[1]   < y < BTN_SET_RED[1]+BTN_SET_RED[3]:
                edit_color, detecting = 'red', False
                touch_released = False
            elif BTN_SET_GREEN[0] < x < BTN_SET_GREEN[0]+BTN_SET_GREEN[2] and BTN_SET_GREEN[1] < y < BTN_SET_GREEN[1]+BTN_SET_GREEN[3]:
                edit_color, detecting = 'green', False
                touch_released = False
            elif BTN_SET_BLUE[0]  < x < BTN_SET_BLUE[0]+BTN_SET_BLUE[2]  and BTN_SET_BLUE[1]  < y < BTN_SET_BLUE[1]+BTN_SET_BLUE[3]:
                edit_color, detecting = 'blue', False
                touch_released = False

        # 颜色阈值滑条与保存按钮逻辑
        if edit_color:
            idx = COLOR_NAMES.index(edit_color)
            sx_save = 320 - 40  # 保存按钮的x坐标
            if sx_save <= x <= sx_save + 35 and 5 <= y <= 25:
                save_data(thresholds, light)
                edit_color = None
                touch_released = False
            else:
                for i in range(6):
                    sx, sy = 5, SLIDER_Y0 + i*STEP
                    if sx <= x <= sx + SLIDER_W and sy <= y <= sy + SLIDER_H:
                        vmin, vmax = RANGE[i]
                        thresholds[idx] = tuple(
                            list(thresholds[idx][:i]) +
                            [clamp(int((x - sx) / SLIDER_W * (vmax - vmin) + vmin), vmin, vmax)] +
                            list(thresholds[idx][i+1:])
                        )
                        touch_released = False
                        break

        # PWM 滑条逻辑
        if pwm_editing:
            sx, sy = 5, SLIDER_Y0
            sw, sh = SLIDER_W, SLIDER_H  # 滑条宽度和高度
            if sx <= x <= sx + sw and sy <= y <= sy + sh:
                light = clamp(int((x - sx) / sw * 100), 0, 100)
                ch.pulse_width_percent(light)
                save_data(thresholds, light)
                touch_released = False

    # ---------- 显示部分 ----------
    if pwm_editing:
        blend = img.copy()
        sx, sy = 5, SLIDER_Y0
        sw, sh = SLIDER_W, SLIDER_H  # 滑条宽度和高度
        ratio = light / 100.0
        pos = sx + int(ratio * sw)
        # 使用全局透明度变量
        blend.draw_rectangle((sx, sy, sw, sh), fill=True, color=(60, 60, 60), alpha=SLIDER_ALPHA)
        blend.draw_rectangle((pos-6, sy-6, 12, sh+12), fill=True, color=(255, 255, 255), alpha=SLIDER_ALPHA)
        blend.draw_string(0, sy-10, "Backlight", scale=1, color=(255, 255, 255))
        blend.draw_string(sx + sw + 5, sy-10, str(light), scale=1, color=(255, 255, 255))
        # 绘制保存按钮
        sx_save = 320 - 40
        blend.draw_rectangle((sx_save, 5, 35, 20), color=(0, 255, 0), thickness=2)
        blend.draw_string(sx_save + 2, 7, "SAVE", scale=1, color=(0, 0, 0))
        lcd.write(blend)

    elif edit_color:
        idx = COLOR_NAMES.index(edit_color)
        th = thresholds[idx]
        mask = img.copy().binary([th])
        blend = img.blend(mask, alpha=128)
        for i in range(6):
            vmin, vmax = RANGE[i]
            sx, sy = 5, SLIDER_Y0 + i*STEP
            sw, sh = SLIDER_W, SLIDER_H  # 滑条宽度和高度
            ratio = (thresholds[idx][i] - vmin) / (vmax - vmin)
            pos = 5 + int(ratio * sw)
            # 使用全局透明度变量
            blend.draw_rectangle((sx, sy, sw, sh), fill=True, color=(60, 60, 60), alpha=SLIDER_ALPHA)
            blend.draw_rectangle((pos-6, sy-6, 12, sh+12), fill=True, color=(255, 255, 255), alpha=SLIDER_ALPHA)
            blend.draw_string(0, sy-8, LABELS[i], scale=1, color=(255, 255, 255))
            blend.draw_string(sx + sw + 5, sy-8, str(thresholds[idx][i]), scale=1, color=(255, 255, 255))
        # 绘制保存按钮
        sx_save = 320 - 40
        blend.draw_rectangle((sx_save, 5, 35, 20), color=(0, 255, 0), thickness=2)
        blend.draw_string(sx_save + 2, 7, "SAVE", scale=1, color=(0, 0, 0))
        lcd.write(blend)

    else:
        draw_btn(img, BTN_DET_RED,   "DET-R", color_map['red'])
        draw_btn(img, BTN_DET_GREEN, "DET-G", color_map['green'])
        draw_btn(img, BTN_DET_BLUE,  "DET-B", color_map['blue'])
        draw_btn(img, BTN_SET_RED,   "SET-R", color_map['red'])
        draw_btn(img, BTN_SET_GREEN, "SET-G", color_map['green'])
        draw_btn(img, BTN_SET_BLUE,  "SET-B", color_map['blue'])
        draw_btn(img, BTN_PWM,       "PWM",   (255, 255, 255))
        if detecting:
            draw_btn(img, BTN_EXIT, "EXIT", (255, 0, 0))
            idx = COLOR_NAMES.index(detect_color)
            th = thresholds[idx]
            for b in img.find_blobs([th], pixels_threshold=100, area_threshold=100):
                img.draw_rectangle(b.rect(), color=color_map[detect_color])
                img.draw_cross(b.cx(), b.cy(), color=(255,255,255))
                print(detect_color, b.cx(), b.cy(), b.area())
        lcd.write(img)
